`include "timescale.v"

module tb_ahb_ctrl();
reg 		   	  hresetn;
reg 			  hclk;
	
	wire [31:0]  haddr;
	wire [1:0]   htrans;
	wire 		   hwrite;
	wire [2:0]   hsize;
	wire [2:0]   hburst;
	wire [3:0]   hprot;
	wire [31:0]  hwdata;

	// output 		   hsel;

wire 			  hready;
wire  	  [1:0]   hresp;
wire  	  [31:0]  hrdata; 

reg 		   	  LatchTx; 						//the start signal

wire 			  ReadFrameState;

////////////////////////////////////////////////////////////////////////////////////////////////////
// regs written by APB
reg 	  [31:0]  MAC_REGS [3:0];				//4 regs for mac config
`define TX_CTRL [0]
`define RX_CTRL [1]
`define TX_BD_PTR [2]
`define RX_BD_PTR [3]
// MAC_REGS`TX_CTRL


////////////////////////////////////////////////////////////////////////////////////////////////////
// ahb_ctrl U_ahb_ctrl(
ahb_ctrl_byte U_ahb_ctrl(				//reading Tx buffer by bytes
  .hresetn(hresetn),
  .hclk(hclk),
	
	.haddr(haddr),
	.htrans(htrans),
	.hwrite(hwrite),
	.hsize(hsize),
	.hburst(hburst),
	.hprot(hprot),
	.hwdata(hwdata),

	// output 		   hsel(),

	.hready					(hready),
	.hresp(hresp),
	.hrdata(hrdata), 

	.tx_bd_pointer			(32'h0000_0400),
	.LatchTx				(LatchTx),				//the start signal

	.ReadFrameState			(ReadFrameState)
);

//clk and reset
wire 			  Gtx_clk;						//from RS
wire 			  Rx_clk;						//from PHY

// ============================== for Tx fifo ==============================
reg 			  ReadFrameState_q;
always@(posedge hclk)
begin
  ReadFrameState_q <= ReadFrameState;
end

wire 			  tx_fifo_wr_en;
wire 	  [7:0]   tx_fifo_data_in;
assign 			  tx_fifo_wr_en  = ReadFrameState_q & hready;
assign 			  tx_fifo_data_in = hrdata[7:0];

// ????????????????????
reg 			  tx_fifo_rd_en;
initial begin
  tx_fifo_rd_en = 1'b1;
end
// ????????????????????

wire 	  [7:0]   tx_fifo_data_out;
wire 			  tx_fifo_empty;
wire 			  tx_fifo_full;

//asfifo
asfifo #(
		 .data_width(8),
		 .address_width(11)		//depth 2048
		 ) U_txfifo (
						.data_out (tx_fifo_data_out),
						.empty (tx_fifo_empty),
						.read_en (tx_fifo_rd_en),
						.clk_read (Gtx_clk),
						
						.data_in(tx_fifo_data_in),
						.full(tx_fifo_full),
						.write_en(tx_fifo_wr_en),
						.clk_write(hclk),
						
						.rst(~hresetn)
						);
////////////////////////////////////////////////////////////////////////////////////////////////////
// onu_mux
// generate PAUSE frame




////////////////////////////////////////////////////////////////////////////////////////////////////
// onu_classifier


////////////////////////////////////////////////////////////////////////////////////////////////////
// onu_rx
// wire 			  mpcp_pause_addr_ok, oam_addr_ok;
wire 			  Rx_dv, Rx_er;
wire 	  [7:0]   Rxd;

wire 			  StateData;

  
onu_rx U_onu_rx(
	.reset					(~hresetn),
	.Rx_clk					(Rx_clk),			//from PHY
	.Rx_dv					(Rx_dv),
	.Rx_er					(Rx_er),
	.Rxd					(Rxd),

	.MAC					(48'h4012_3456_789A),
	.transmitting			(1'b0),

	//states
	.StateData_o			(StateData),
	.len_type				(),

	.UnicastOK				(), 
	.BroadcastOK			(), 
	.MulticastOK(),
	.MPCP_PAUSE_MultiAddr_OK(),
	.OAM_MultiAddr_OK		()
	);

////////////////////////////////////////////////////////////////////////////////////////////////////
wire 	  [7:0]   rx_fifo_data_out;
wire 			  rx_fifo_empty;
wire 			  rx_fifo_full;
wire 			  rx_fifo_rd_en;

assign 			  rx_fifo_wr_en = StateData;

assign 			  rx_fifo_rd_en = 1'b1;

//asfifo
asfifo #(
		 .data_width(8),
		 .address_width(11)		//depth 2048
		 ) U_rxfifo (
						.data_out (rx_fifo_data_out),
						.empty (rx_fifo_empty),
						.read_en (rx_fifo_rd_en),
						.clk_read (hclk),
						
						.data_in(Rxd),
						.full(rx_fifo_full),
						.write_en(rx_fifo_wr_en),
						.clk_write(Rx_clk),
						
						.rst(~hresetn)
						);
////////////////////////////////////////////////////////////////////////////////////////////////////
// onu_tx
wire 			  Tx_en, Tx_er;
wire 	  [7:0]   Txd;
onu_tx U_onu_tx(
	.reset					(~hresetn),
	
	.Tx_clk					(Gtx_clk),			//GMII interface 
	.Tx_en					(Tx_en),
	.Tx_er					(Tx_er),
	.Txd					(Txd),

	.MinFL					(16'h40),
	.MaxFL					(16'h600),
	.IPGT					(4'd12),

	// .TxStartFrm				(TxStartFrm),
	// .TxEndFrm				(TxEndFrm),

	.TxStartFrm				(~tx_fifo_empty),
	.TxEndFrm				(tx_fifo_empty),
	

	.TxUnderRun				(1'b0),

	.h_tx_data				(tx_fifo_data_out),			//from fifo 
	
	//output 
	.StatePreamble			(),
	.StateData				()
	);




////////////////////////////////////////////////////////////////////////////////////////////////////
//PHY
wire 			  Col, Crs;
onu_phy U_onu_phy(
	.Gtx_clk				(Gtx_clk)				, //used only in GMII mode
	.Tx_en 					(Tx_en)					,
	.Tx_er 					(Tx_er)					,
	.Txd					(Txd)					,
	
	.Rx_clk					(Rx_clk)					,
	.Rx_dv					(Rx_dv)					,
	.Rx_er					(Rx_er)					,
	.Rxd					(Rxd)					,
	
	.Col					(Col)						,	
	.Crs					(Crs)						
	);

////////////////////////////////////////////////////////////////////////////////////////////////////
// RS  -- supply the Gtx_clk
RS U_RS(
	.Gtx_clk				(Gtx_clk)
	);


////////////////////////////////////////////////////////////////////////////////////////////////////
wire 			  hsel ;
assign 			  hsel 		  = 1;
ahb_ram_if U_ahb_ram(
			  .hresetn(hresetn),
			  .hclk(hclk),
			  .hsel(hsel),	
			  .haddr(haddr),
			  .htrans(htrans),
			  .hwrite(hwrite),
			  .hsize(hsize),
			  .hburst(hburst),
			  .hprot(hprot),
			  .hwdata(hwdata),

	.hready					(hready),
	.hresp					(hresp),
	.hrdata					(hrdata) 
);

// always@(posedge hclk or negedge hresetn)
// begin
//   if(!hresetn)
// 	$ahb_ram_init();
//   else 
// 	$ahb_ram(haddr, htrans, hwrite, hsize, hburst, hprot, hwdata, hresp, hrdata);		//sel is not used
// end


initial begin
hclk = 0;
forever #3 hclk = ~hclk;
end

initial begin
hresetn = 0; LatchTx = 0;
#10 hresetn = 1;

// #100 LatchTx = 1;
#10 LatchTx = 0;
end

// initial begin
// hresp = 2'b00;
// forever #10 #1 hrdata = $random;
// end

endmodule // tb_ahb_ctrl


